<?php
/**
 * 根对象
 *
 * @package if
 * @subpackage core
 * @version $Id$
 * @since 1.0
 */
class IObject implements ArrayAccess {
	private $refId;
	private $time;
	private $microtime;
	
	/**
	 * 取得引用标识ID
	 *
	 * @return string
	 * @since 1.0
	 */
	function _refId() {
		if (!$this->refId) {
			$this->refId = str_replace(".", "_",  uniqid(__CLASS__ . "_", true));
			IRegistry::singleton()->addRef($this);
		}
		return $this->refId;
	}
	

	/**
	 * 打印当前对象
	 *
	 * @param boolean $return 是否以字符串返回
	 * @return null|string
	 * @since 1.0
	 */
	function _dump($return = false) {
		if ($return) {
			return print_r($this, true);
		}
		p($this);
	}
	
	/**
	 * 取得当前的时间戳
	 *
	 * @param boolean $refresh 是否刷新
	 * @return integer
	 * @since 1.0
	 */
	protected function _time($refresh = false) {
		if (!$this->time || $refresh) {
			$this->time = time();
		}
		return $this->time;
	}
	
	/**
	 * 取得当前的时间(时间戳.微秒)
	 *
	 * @param boolean $refresh 是否刷新
	 * @return float
	 * @since 1.0
	 */
	protected function _microtime($refresh = false) {
		if (!$this->microtime || $refresh) {
			$this->microtime = microtime(true);
		}
		return $this->microtime;
	}
	
	/**
	 * 新增日志
	 *
	 * @param string $msg 消息
	 * @param integer $level 级别，为ILog::LOG_XXX
	 * @since 1.0
	 */
	protected function _log($msg, $level = ILog::LOG_DEBUG) {
		ILog::singleton()->log($msg, $level);
	}
	
	/**
	 * 输出调试到浏览器
	 * 
	 * 要想使用该方法，需要加载firephp模块
	 * @param mixed arg1 参数1
	 *	FirePHP::LOG
	 *	FirePHP::INFO
	 *	FirePHP::WARN
	 *	FirePHP::ERROR
	 *	FirePHP::DUMP
	 *	FirePHP::TRACE
	 *	FirePHP::EXCEPTION
	 * @param mixed arg2 参数2
	 * @param mixed ...
	 * @return boolean
	 * @since 1.0
	 */
	protected function _fb() {
		if (IApplication::hasModule("firephp")) {
			$firephp = FirePHP::getInstance(true);
			$args = func_get_args();
			return call_user_func_array(array($firephp, "fb"), $args);
		}
		return false;
	}
	
	/**
	 * 判断一个偏移量是否存在
	 *
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * @param integer $index
	 * @return boolean
	 * @since 1.0
	 */
	function offsetExists($index) {
		$attrs = get_object_vars($this);
		return array_key_exists($index, $attrs);
	}
	
	/**
	 * 从一个偏移量中取得数据
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * 从1.0.2开始起，如果查询不到属性值，将会报错，而不是简单地返回null
	 *
	 * @param integer $index 偏移量
	 * @return mixed
	 * @since 1.0
	 */
	function offsetGet($index) {
		return $this->$index;
	}
	
	/**
	 * 设置偏移量位置上的值
	 *
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * @param integer $index 偏移量
	 * @param mixed $item 值
	 * @since 1.0
	 */
	function offsetSet($index, $item) {
		$this->$index = $item;
	}
	
	/**
	 * 删除偏移量位置对应的元素
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param integer $index 偏移量
	 * @since 1.0
	 */
	function offsetUnset($index) {
		if ($this->offsetExists($index)) {
			unset($this->$index);
		}
	}	
	
	/**
	 * 执行表达式
	 *
	 * @param mixed $expr 表达式
	 * @param IObject $object 作用域对象
	 * @return mixed
	 * @since 1.0
	 */
	protected function _expr($expr, IObject $object = null) {
		if (is_null($object)) {
			$object = $this;
		}
		$class = get_class($object);
		if (is_bool($expr) || is_null($expr) || is_numeric($expr)) {
			return $expr;
		}
		else if (is_string($expr)) {
			$directive = null;
			if (strstr($expr, ":")) {
				list($directive, $expr) = explode(":", $expr, 2);
			}
			if ($directive == "expr") {
				$expr = preg_replace("/(^|\b)self::/i", $class . "::", $expr);
				$expr = preg_replace("/\\\$this->/i", "\$object->", $expr);
				$value = null;
				if (eval("\$value=" . $expr . ";") === false) {
					throw new IException("parse expr \"{$expr}\" error", 0x100011);	
				}
				return $value;
			}
			else {
				return $expr;
			}
		}
		else {
			return $expr;
		}
	}
}

?>